package com.atguigu.gmall.mq;




import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.autoconfigure.amqp.RabbitTemplateConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;


/**
 * RabbitMq的自动配置
 * RabbitPropERties 封装所有可以配置属性
 * RabbitTemplateConfigurer: 自定义修改 RabbitTemplate
 * RabbitTemplate: RedisTemplate, ElasticSearchTemplate; 操作rabbitmq的客户端
 * AmqAdmin 管理RabbitMQ，增删改查queue exchange等
 */
@EnableRabbit
@Configuration
public class AppRabbitConfig {

    /**
     *  String name,  交换机名字
     *  boolean durable,  持久化
     *  boolean autoDelete  是否自动删除
     *  Map<String, Object> arguments, 交换机的参数配置
     *
     * @return
     */
    public Exchange orderEventExchange(){
         return new TopicExchange(RabbitConst.ORDER_EXCHANGE,true,false);

    }

    @Bean
    public Queue orderDelayQueue(){
        /**
         * String name, 队列的名字
         * boolean durable, 持久化
         * boolean exclusive,   排他的
         * boolean autoDelete,  自动删除
         * @Nullable Map<String, Object> arguments
         */
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange",RabbitConst.ORDER_EXCHANGE);
        arguments.put("x-dead-letter-routing-key","order.release.order");
        arguments.put("x-message-ttl",60000*30);//1min过期
        return new Queue(RabbitConst.ORDER_DELAY_QUEUE,true,false,false,arguments);
    }

    @Bean
    public Queue orderReleaseOrderQueue(){
        return new Queue(RabbitConst.ORDER_RELEASE_QUEUE,true,false,false);
    }

    /**
     * 交换机和延时队列
     * @return
     */
    @Bean
    public Binding orderCreateOrderBinding(){
        /**
         * String destination, 目的地
         * DestinationType destinationType, 目的地类型
         * String exchange, 交换机
         * String routingKey, 路由键
         * @Nullable Map<String, Object> arguments 参数设置项
         */
        return new Binding(RabbitConst.ORDER_DELAY_QUEUE,
                Binding.DestinationType.QUEUE,
                RabbitConst.ORDER_EXCHANGE,
                RabbitConst.CREATE_ORDER_RK,null);
    }

    /**
     * 交换机和死信队列的绑定
     * @return
     */
    @Bean
    public Binding releaseOrderBinding(){

        return new Binding(RabbitConst.ORDER_RELEASE_QUEUE,
                Binding.DestinationType.QUEUE,
                RabbitConst.ORDER_EXCHANGE,
                "order.release.order",null);
    }


    /**
     * 手动模式
     * @param configurer
     * @param connectionFactory
     * @return
     */
    @Bean
    public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate();
        configurer.configure(template, connectionFactory);
        //CorrelationData correlationData, boolean ack, @Nullable String cause
        //correlationData 发送消息的数据是什么
        //ack 消息是否回复成功或失败
        //@Nullable String cause
        template.setConfirmCallback((correlationData,ack,cause)->{
            if (ack){
                System.out.println("服务器收到了消息.........");
            }else{
                System.out.println("没有收到消息..."+correlationData.getReturnedMessage());
            }
        });
        //Message message, int replyCode, String replyText, String exchange, String routingKey
        template.setReturnCallback((message,replyCode,replyText,exchange,routingKey)->{
            System.out.println(message + ":投递到队列失败");
            System.out.println("响应状态码:" + replyCode);
            System.out.println("响应文本:" +replyText);
            System.out.println("服务器收到的消息: " +message);
            System.out.println("消息交换机: " +exchange);
        });
        return template;
    }

}
